#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>

/******************** Edge ********************/
typedef struct {
	int id1;
	int id2;
	double weight;
	int matbeg_id;
	int indval_index; 
	int edge_id;
	int clusterID;
}Edge;


/******************** LinkedList ********************/
struct LinkedList {
  struct LinkedList* next;
  struct LinkedList* prev;
  Edge* e;
};

typedef struct LinkedList LinkedList;

/******************** Vertex ********************/
typedef struct{
	char* name;
	int id;
	LinkedList* edges;
	int degree;
	int clusterID;
	int matbeg_id;
	int indval_index; /* indval_index is initially taken from matbeg */
	int instance_number;
}Vertex;

/******************** Network ********************/
typedef struct{
	Vertex** vertices;
	int size;
	int maxSize;
	double weightsSum;
	int totalEdgeNumber;
	LinkedList *edge_list_head;
	LinkedList *edge_list_current;
}Network;


/******************* Iterators **********************/
typedef struct {
	Network *network;
	Vertex *currnet_vertex;
	int vertex_id;
	Edge *currnet_edge;
	LinkedList *current_link;
	int *edge_array;
} iterator;

typedef struct {
	Network *network;
	Vertex *currnet_vertex;
	int cur_vertex_id;
} vertex_iterator;

typedef struct {
	Network *network;
	Edge *currnet_edge;
	LinkedList *current_link;
} edge_iterator;


/********************** Queue ***********************/

typedef struct{
        int capacity; /* max. size of the queue*/
        int current_size;
        int front; /*first in line*/
        int rear;  /*last in line*/
        int *elements;
}Queue_fifo;


/****************** XGMML structs ******************/

typedef struct {
	int size;
	double sumOfWeights;
	int clusterId;
	int touchedForMaxWeight;
}ClusterSize;




/*******************************************************/
/******************** Functions ************************/
/*******************************************************/



/****************** LinkedList functions prototype ******************/

LinkedList* HeadInsert(LinkedList* listHead, Edge* newEdge);
LinkedList* DeleteHead(LinkedList* listHead);
LinkedList* DeleteItem(LinkedList* item);
LinkedList* getEdgeLink(LinkedList* head, int firstVertexID, int secondVertexID);
void printList (LinkedList* list);

/****************** Network functions prototype ******************/

Network* createNetwork();
void printNet(Network* net);

/****************** Vertex functions prototype ******************/

Vertex* createVertex(int id, char* name);

/****************** Edge functions prototype ******************/

Edge* createEdge(int id1, int id2, double weight);


/****************** Iterator functions ******************/
/*Vertices*/
void new_vertex_iterator(Network *net, vertex_iterator *iter);
int hasNextVertex(vertex_iterator iter);
void next_vertex_NEW(vertex_iterator *iter);
/*Edges*/
int new_edge_iterator(Network *net, edge_iterator *iter);
int hasNextEdge_NEW(edge_iterator iter);
void next_edge_NEW(edge_iterator *iter);
/*General iterator functions*/
void clean_iterator_index(vertex_iterator *ver_iter, edge_iterator *edge_iter);

/* Queue functions */
Queue_fifo * createQueue(int maxElements);
void Dequeue(Queue_fifo *Q);
int get_front(Queue_fifo *Q);
void Enqueue(Queue_fifo *Q,int element);
void delete_queue(Queue_fifo *queue);
int is_queue_empty(Queue_fifo *queue);








